﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace SscLib
{
    /// <summary>
    /// Defines an Argument symbol. Arguments are parameters to methods and construtors.
    /// </summary>
    public class ArgumentSymbol : Symbol
    {
        /// <summary>Indexed address (position) for this Argument symbol.</summary>
        public int Adr;

        /// <summary>Specifies that this argument is a pass by Name parameter.</summary>
        public bool NameParam;

        /// <summary>Specifies that this argument is a pass by Value parameter.</summary>
        public bool ValueParam;

        //public ParameterInfo Info; TODO: verify that we do not need the ParameterInfo metadata field.

        public override TypeSymbol Type
        {
            get
            {
                if (NameParam) return this._type.GetByRefType();
                return this._type;
            }
            set
            {
                base._type = value;
            }
        }

        /// <summary>
        /// Constructs an Argument Symbol, with name, type and containing scope.
        /// </summary>
        /// <param name="name">Argument name.</param>
        /// <param name="type">Argument type.</param>
        internal ArgumentSymbol(string name, TypeSymbol type)
            : base(name, type)
        {
        }

        /// <summary>
        /// Returns the System Type (native .Net type) of this argument.
        /// Converts to a reference type if this is a pass by Name parameter.
        /// </summary>
        // TODO: Named parameters in Simula is evaluated before every use, event for expressions passed to a pass-by-name parameter.
        // In idea to implement this is to use a Generic Interface/Class encapsulating the Expression. And at compile time pass every variable used
        //// in the expression as references to the actual intance of the Generic Interface/Class. If so the method below could need to be updated.
        //public override Type SystemType
        //{
        //    get
        //    {
        //        if (NameParam) return this.Type.SystemType.MakeByRefType();
        //        else return base.SystemType;
        //    }
        //}

        /// <summary>
        /// Returns a string that represents this Argument symbol.
        /// </summary>
        /// <returns>Returns a string representation of this Argument symbol.</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Argument({0})", base.ToString());
            return sb.ToString();
        }
    }
}
